home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 46
/
Amiga Format CD46 (1999-10-20)(Future Publishing)(GB)[!][issue 1999-12].iso
/
-serious-
/
programming
/
other
/
gtdrag
/
examples
/
treetest.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-06
|
13KB
|
479 lines
;/* treetest.c - Test for the gtdrag.library, 7.6.1999
;**
;** Copyright ©1999 pinc Software.
;** All rights reserved.
;**
sc treetest.c link lib=lib:debug.lib ign=73 nodbg data=near parm=b nochkabort nostkchk strmer streq to=ram:treetest
run ram:treetest
quit
*/
/* This example shows how to use the treeview included in the
** gtdrag-library.
** This is done via a standard gadtools listview and a special
** render hook.
** Furthermore, this example make use of lots of the tree support
** functions of the library.
**
** It's a very simple example but you may use this code to produce
** one at your own.
**
** Although I tried hardly to not produce any errors, I cannot give
** any guaranties. Neither I nor pinc Software is liable for any
** problems you might have with it.
** The usage of this example is on your own risk.
*/
#define INTUI_V36_NAMES_ONLY
#define __USE_SYSBASE
#include <exec/libraries.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <graphics/gfx.h>
#include <graphics/gfxmacros.h>
#include <libraries/gadtools.h>
#include <libraries/gtdrag.h>
#include <libraries/asl.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/exall.h>
#include <dos/dostags.h>
#include <clib/alib_protos.h>
#include <clib/alib_stdio_protos.h>
#include <clib/gtdrag_protos.h>
#include <proto/exec.h>
#include <proto/gadtools.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/layers.h>
#include <proto/utility.h>
#include <proto/dos.h>
#include <pragmas/gtdrag_pragmas.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
/**************** some useful definitions ****************/
void kprintf(STRPTR,...);
#define bug kprintf
#define TLn(t) TextLength(&scr->RastPort,t,strlen(t))
#define foreach(l,v) for(v = (APTR)((struct List *)l)->lh_Head;((struct Node *)v)->ln_Succ;v = (APTR)((struct Node *)v)->ln_Succ)
#define PUDDLESIZE 8192 // for CreatePool()
#define MULTIVIEW "sys:Utilities/Multiview" // "show" programme
#define SEARCH_DIRECTORY "ram:" // directory displayed
#define SEARCH_DEPTH 4 // depth of the tree
#define OUTPUT "CON://400/200/TreeView-Output/AUTO/CLOSE/WAIT"
/**************** the menu definition ****************/
struct NewMenu NMenu[] =
{
{NM_TITLE,"Control", 0,0,0,0},
{NM_ITEM, "Open all", "O",0,0,0},
{NM_ITEM, "Close all", "C",0,0,0},
{NM_ITEM, NM_BARLABEL, 0,0,0,0},
{NM_ITEM, "About...", "?",0,0,0},
{NM_ITEM, "Quit", "Q",0,0,0},
{NM_END, NULL, 0,0,0,0}
};
/**************** global variables ****************/
struct Screen *scr;
struct Window *win;
struct IntuiMessage imsg;
struct Menu *menu;
struct Library *GTDragBase;
struct Gadget *glist,*lvgad,*gad,*button[2];
struct NewGadget ng;
struct Hook hook;
struct TreeList tl;
APTR vi,pool;
int fontheight,itemheight;
BOOL ende = FALSE;
/**************** Requester ****************/
long DoRequestA(STRPTR t,STRPTR gads,APTR args)
{
struct EasyStruct es = {sizeof(struct EasyStruct),0,"TreeView-Request",NULL,NULL};
es.es_TextFormat = t;
es.es_GadgetFormat = gads;
return(EasyRequestArgs(scr->FirstWindow,&es,0,args));
}
void ErrorRequest(STRPTR t,...)
{
DoRequestA(t,"Ok",&t+1);
}
/**************** String functions ****************/
STRPTR AllocString(STRPTR t) // these will be freed at the end of the programme
{
STRPTR s;
if (!t || !*t)
return(NULL);
if (s = AllocPooled(pool,strlen(t)+1))
strcpy(s,t);
return(s);
}
/**************** list functions ****************/
void CloseAllTrees(struct MinList *tree)
{
struct TreeNode *tn;
foreach(tree,tn)
{
if (tn->tn_Flags & TNF_CONTAINER)
{
CloseAllTrees(&tn->tn_Nodes);
tn->tn_Flags &= ~TNF_OPEN;
}
}
}
/**************** main programme ****************/
void processMsg(void)
{
struct IntuiMessage *msg;
struct DropMessage *dm;
int source,target;
int i;
while(!ende)
{
WaitPort(win->UserPort);
while(msg = GTD_GetIMsg(win->UserPort))
{
imsg = *msg;
if (imsg.Class == IDCMP_OBJECTDROP) /* handle the IDCMP_OBJECTDROP message */
{
if ((dm = imsg.IAddress) && !dm->dm_Object.od_Owner)
{
if (dm->dm_Target)
{
target = dm->dm_Target->GadgetID;
source = dm->dm_Gadget->GadgetID;
if (target > 1 && source == 1) // Show or execute
{
struct TreeNode *tn = TREENODE(dm->dm_Object.od_Object);
char t[256];
if (target == 2)
strcpy(t,MULTIVIEW " ");
else
t[0] = 0;
strcat(t,"\"");
strcat(t,SEARCH_DIRECTORY);
if (GetTreePath(tn,t+strlen(t),200))
{
BPTR input;
strcat(t,tn->tn_Node.in_Name);
strcat(t,"\"");
if (input = Open(OUTPUT,MODE_OLDFILE))
{
if (SystemTags(t,SYS_Input, input,
SYS_Output, NULL,
SYS_Asynch, TRUE,
SYS_UserShell, TRUE,
TAG_END) == -1)
{
Close(input);
ErrorRequest("Execution failed:\n %s",t);
}
}
else
ErrorRequest("Could not open output:\n",OUTPUT);
}
}
else if (target == source) // only possible if target == 1
ErrorRequest("Sorry, but I can't move anything!");
}
}
else
DisplayBeep(NULL);
}
GTD_ReplyIMsg(msg);
switch(imsg.Class)
{
case IDCMP_GADGETDOWN:
break;
case IDCMP_GADGETUP:
switch((gad = imsg.IAddress)->GadgetID)
{
case 1:
{
struct TreeNode *tn;
long top;
for(tn = (APTR)tl.tl_View.mlh_Head,i = 0;i < imsg.Code;tn = (APTR)tn->tn_Node.in_Succ,i++);
gad->UserData = tn; tn = TREENODE(tn);
//ToggleTree(gad,tn,&imsg);
/** ToggleTree(gad,tn,&imsg) does something like this: **/
GT_GetGadgetAttrs(gad,win,NULL,GTLV_Top,&top,TAG_END);
if (MouseOverTreeKnob(tn,gad->TopEdge+2+(imsg.Code-top)*itemheight,&imsg))
{
long in,height = (gad->Height-4)/itemheight;
GT_SetGadgetAttrs(gad,win,NULL,GTLV_Labels,~0L,TAG_END);
if ((in = ToggleTreeNode(&tl.tl_View,tn)) && imsg.Code+1+in > top+height)
top += imsg.Code+in+1-top-height;
GT_SetGadgetAttrs(gad,win,NULL,GTLV_Labels,&tl.tl_View,GTLV_Top,top,TAG_END);
}
break;
}
}
break;
case IDCMP_MENUPICK:
i = 0;
switch ITEMNUM(imsg.Code)
{
case 1:
i = TNF_OPEN;
case 0:
{
struct TreeNode *ln,*tn;
GT_SetGadgetAttrs(lvgad,win,NULL,GTLV_Labels,~0L,TAG_END);
foreach(&tl,ln)
{
tn = TREENODE(ln);
if ((tn->tn_Flags & TNF_OPEN) == i)
ToggleTreeNode(&tl,tn);
}
if (ITEMNUM(imsg.Code) == 1) // close all sub-directories, see above
CloseAllTrees(&tl.tl_Tree);
GT_SetGadgetAttrs(lvgad,win,NULL,GTLV_Labels,&tl.tl_View,GTLV_Top,0,TAG_END);
break;
}
case 3:
ErrorRequest("TreeView - a gtdrag example\n\n©1999 pinc Software.\nAll Rights Reserved.");
break;
case 4:
ende = TRUE;
break;
}
break;
case IDCMP_CLOSEWINDOW:
ende = TRUE;
break;
}
}
}
}
struct Window *initWindow(void)
{
struct Window *win;
gad = CreateContext(&glist);
ng.ng_LeftEdge = 8;
ng.ng_TopEdge = fontheight+7;
ng.ng_Width = 184;
ng.ng_Height = 14*itemheight+4;
ng.ng_VisualInfo = vi;
ng.ng_TextAttr = scr->Font;
ng.ng_GadgetText = NULL;
ng.ng_UserData = NULL;
ng.ng_GadgetID = 1;
lvgad = CreateGadget(LISTVIEW_KIND,gad,&ng,GTLV_Labels,&tl,GTLV_CallBack,&hook,GTLV_ItemHeight,itemheight,TAG_END);
ng.ng_TopEdge += ng.ng_Height;
ng.ng_LeftEdge = 8;
ng.ng_Height = fontheight+4;
ng.ng_Width >>= 1;
ng.ng_Flags = PLACETEXT_IN;
ng.ng_GadgetText = "Show";
ng.ng_GadgetID++;
button[0] = CreateGadget(BUTTON_KIND,lvgad,&ng,GA_Immediate,TRUE,TAG_END);
ng.ng_LeftEdge += ng.ng_Width;
ng.ng_GadgetText = "Execute";
ng.ng_GadgetID++;
button[1] = CreateGadget(BUTTON_KIND,button[0],&ng,TAG_END);
if (win = OpenWindowTags(NULL,WA_Title, "gtdrag - TreeView",
WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_ACTIVATE,
WA_IDCMP, IDCMP_CLOSEWINDOW | DRAGIDCMP | IDCMP_MENUPICK,
WA_Width, 200,
WA_NewLookMenus,TRUE,
WA_Height, itemheight*14+3*fontheight+10,
WA_Gadgets, glist,
TAG_END))
{
SetMenuStrip(win,menu);
GT_RefreshWindow(win,NULL);
GTD_AddGadget(LISTVIEW_KIND,lvgad,win,GTDA_RenderHook,&hook,
GTDA_Type, ODT_TREENODE,
GTDA_ItemHeight,itemheight,
GTDA_Same, TRUE,
GTDA_TreeView, TRUE,
TAG_END);
GTD_AddGadget(BUTTON_KIND,button[0],win,TAG_END);
GTD_AddGadget(BUTTON_KIND,button[1],win,TAG_END);
return(win);
}
return(NULL);
}
void GetDirectoryTree(struct MinList *tree,STRPTR name,int depth)
{
APTR edbuffer;
BPTR lock;
if (!depth)
return;
if (edbuffer = AllocPooled(pool,PUDDLESIZE))
{
if (lock = Lock(name,ACCESS_READ))
{
struct ExAllControl *eac;
struct ExAllData *ed;
long more;
if (eac = AllocDosObject(DOS_EXALLCONTROL,NULL))
{
struct TreeNode *tn;
do
{
more = ExAll(lock,edbuffer,PUDDLESIZE,ED_TYPE,eac);
if (eac->eac_Entries == 0)
break;
for(ed = edbuffer;ed;ed = ed->ed_Next)
{
if (!strcmp(ed->ed_Name+strlen(ed->ed_Name)-5,".info"))
continue;
tn = AddTreeNode(pool,tree,AllocString(ed->ed_Name),NULL,(ed->ed_Type == ST_USERDIR ? TNF_CONTAINER | TNF_HIGHLIGHTED : TNF_NONE) | TNF_SORT);
if (tn && ed->ed_Type == ST_USERDIR && depth > 1)
{
BPTR old;
old = CurrentDir(lock);
GetDirectoryTree(&tn->tn_Nodes,ed->ed_Name,depth-1);
CurrentDir(old);
}
}
} while(more);
FreeDosObject(DOS_EXALLCONTROL,eac);
}
UnLock(lock);
}
FreePooled(pool,edbuffer,PUDDLESIZE);
}
}
void init(void)
{
CopyMem(GTD_GetHook(GTDH_TREE),&hook,sizeof(struct Hook));
hook.h_Data = (APTR)FindColor(scr->ViewPort.ColorMap,0x44444444,0x44444444,0x44444444,-1);
NewList((struct List *)&tl.tl_Tree);
GetDirectoryTree(&tl.tl_Tree,SEARCH_DIRECTORY,SEARCH_DEPTH);
InitTreeList(&tl);
}
void main(int argc, char **argv)
{
if (GTDragBase = OpenLibrary("gtdrag.library",3))
{
if (GTD_AddApp("treetest",GTDA_NewStyle,TRUE,TAG_END))
{
if (pool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR,PUDDLESIZE,PUDDLESIZE))
{
if (scr = LockPubScreen(NULL))
{
vi = GetVisualInfo(scr,TAG_END);
fontheight = scr->Font->ta_YSize;
itemheight = fontheight+2;
init();
if (menu = CreateMenus(NMenu,TAG_END))
{
if (LayoutMenus(menu,vi,GTMN_NewLookMenus, TRUE,
TAG_END))
{
if (win = initWindow())
{
processMsg();
CloseWindow(win);
}
FreeGadgets(glist);
FreeMenus(menu);
}
}
FreeVisualInfo(vi);
UnlockPubScreen(NULL,scr);
}
DeletePool(pool);
}
GTD_RemoveApp();
}
CloseLibrary(GTDragBase);
}
else
ErrorRequest("Could not open the gtdrag.library v3 or higher.");
}